/*
 * StreamLog.h
 *
 *  Created on: 2012-12-26
 *      Author: yangentao@gmail.com
 */

#pragma once;

#include <string>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include "AutoLock.h"
#include "SparseArray.h"

#define SLOG_MSG	0
#define SLOG_TAG	1
#define SLOG_TITLE	2

namespace yet {

enum LogLevel {
	logVerbose, logInfo, logDebug, logWarn, logError,
};
class LogMsg {
public:
	LogMsg();
public:
	void init();
	string toString();
	void setTimePidTid();
public:
	LogLevel level;
	string tag;
	string title;
	string msg;
public:
	SYSTEMTIME time;
	DWORD pid;
	DWORD tid;
};

class LogHandlerNode;
class LogConnection {
	friend class LogHandlerList;
public:
	LogConnection();
public:
	void disconnect();
private:
	LogHandlerNode* node;
};

//return true will block the next handlers
typedef boost::function<bool(LogMsg)> LogHandler;


class MsgField {
public:
	MsgField();
	MsgField(int flag, string value);
public:
	int flag; //0: msg; 1: tag; 2:title
	string value;
};
class StreamLog : ThreadLock{
	friend class LogConnection;
public:
	StreamLog();
	virtual ~StreamLog();
public:
	void append(string s);
	void write();
	void setField(MsgField field);
	void setLevel(LogLevel level);
	LogConnection pushLogHandler(LogHandler handler);
	LogConnection pushLogHandler(LogHandler handler, string tag1, string tag2="", string tag3="", string tag4="", string tag5="");

private:
	LogMsg* getMsg();
private:
	LogMsg mainMsg;
	SparseArray<boost::shared_ptr<LogMsg>  > threadMsgs;
	LogHandlerList* handlers;
};



StreamLog& operator <<(StreamLog& slog, StreamLog& (*fun)(StreamLog&));
StreamLog& operator <<(StreamLog& slog, MsgField& msgField);

StreamLog& end(StreamLog& slog);
StreamLog& endln(StreamLog& slog);

MsgField tag(string s);
MsgField msg(string s);
MsgField title(string s);

StreamLog& verbose(StreamLog& slog);
StreamLog& verb(StreamLog& slog);
StreamLog& info(StreamLog& slog);
StreamLog& err(StreamLog& slog);
StreamLog& error(StreamLog& slog);
StreamLog& warn(StreamLog& slog);
StreamLog& dbg(StreamLog& slog);
StreamLog& debug(StreamLog& slog);

StreamLog& space(StreamLog& slog);
StreamLog& sp(StreamLog& slog);
StreamLog& tab(StreamLog& slog);

StreamLog& operator <<(StreamLog& slog, bool val);
StreamLog& operator <<(StreamLog& slog, char val);
StreamLog& operator <<(StreamLog& slog, unsigned char val);
StreamLog& operator <<(StreamLog& slog, short val);
StreamLog& operator <<(StreamLog& slog, unsigned short val);
StreamLog& operator <<(StreamLog& slog, wchar_t val);
StreamLog& operator <<(StreamLog& slog, int val);
StreamLog& operator <<(StreamLog& slog, unsigned int val);
StreamLog& operator <<(StreamLog& slog, long val);
StreamLog& operator <<(StreamLog& slog, unsigned long val);

StreamLog& operator <<(StreamLog& slog, float val);
StreamLog& operator <<(StreamLog& slog, double val);
StreamLog& operator <<(StreamLog& slog, long double val);

StreamLog& operator <<(StreamLog& slog, const char* s);
StreamLog& operator <<(StreamLog& slog, const string& s);

StreamLog& operator <<(StreamLog& slog, const wchar_t* ws);
StreamLog& operator <<(StreamLog& slog, const wstring& ws);

extern StreamLog slog;

} /* namespace yet */
